package ThroughputDelay.IO;

import ThroughputDelay.DataGenerator;

import java.io.DataInputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

public class ServerThrDelIO {

    public static enum MEASUREMENT_MODE {
        THROUGHPUT,
        DELAY
    }
    public static final int POOL_SIZE = 10;
    public static final int MESSAGE_COUNT = 10000;
    public static final MEASUREMENT_MODE mode = MEASUREMENT_MODE.DELAY;

    public static void main(String[] args) throws IOException, InterruptedException {
        ServerSocket serverSocket = new ServerSocket(7003);
        AtomicInteger counter = new AtomicInteger();
        long begin, end;

        List<Thread> threadPool = new ArrayList<>();
        for (int i = 0; i < POOL_SIZE; i++) {
            Socket socket = serverSocket.accept();
            Thread thr = new Thread(() -> {
                try (
                        ObjectOutputStream os = new ObjectOutputStream(socket.getOutputStream());
                        DataInputStream is = new DataInputStream(socket.getInputStream())) {

                    String line;
                    boolean running = true;
                    long start = 0, finish = 0;
                    int localCounter = 0;
                    long delaySum = 0;
                    while (running) {

                        switch (mode) {
                            case THROUGHPUT:
                                for (int j = 0; j < MESSAGE_COUNT; j++) {
                                    os.writeObject(DataGenerator.generate());
                                    counter.getAndIncrement();
                                }
                                running = false;
                                break;
                            case DELAY:
                                line = is.readUTF();
                                switch (line) {
                                    case "GET":
                                        start = System.currentTimeMillis();
                                        os.writeObject(DataGenerator.generate());
                                        break;
                                    case "CONFIRM":
                                        counter.getAndIncrement();
                                        localCounter++;
                                        finish = System.currentTimeMillis();
                                        delaySum += finish - start;
                                        break;
                                    case "STOP":
                                        running = false;
                                        break;
                                }
                                break;
                        }
                    }
                    if (mode == MEASUREMENT_MODE.DELAY)
                        System.out.println("Average delay: " + delaySum / localCounter);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            });
            threadPool.add(thr);
        }

        System.out.println("launch");
        begin = System.currentTimeMillis();
        for (Thread thr : threadPool){
            thr.start();
        }
        for (Thread thr : threadPool){
            thr.join();
        }

        end = System.currentTimeMillis();
        if (mode == MEASUREMENT_MODE.THROUGHPUT)
            System.out.println("Throughput: " + counter.get() / (end / 1000.0 - begin / 1000.0));
    }
}
